//
//  YYAlamofire.swift
//  YYProject
//
//  Created by 陆文宇 on 2017/8/10.
//  Copyright © 2017年 陆文宇. All rights reserved.
//

import Alamofire

func yy_get(url: URLConvertible, parameters: [String: String]? = nil, success: @escaping (Any?) -> Void, failure: @escaping (String) -> String?) {
    _ = YYAlamofire.get(url: url, parameters: parameters, success: success, failure: failure)
}

func yy_post(url: URLConvertible, parameters: [String: String]? = nil, success: @escaping (Any?) -> Void, failure: @escaping (String) -> String?) {
    _ = YYAlamofire.post(url: url, parameters: parameters, success: success, failure: failure)
}

func yy_getForCache(url: URLConvertible, parameters: [String: String]? = nil, cache: (Any?) -> Bool, success: @escaping (Bool, Any?) -> Void, failure: @escaping (String, Any?) -> String?) {
    _ = YYAlamofire.getForCache(url: url, parameters: parameters, cache: cache, success: success, failure: failure)
}

func yy_postForCache(url: URLConvertible, parameters: [String: String]? = nil, cache: (Any?) -> Bool, success: @escaping (Bool, Any?) -> Void, failure: @escaping (String, Any?) -> String?) {
    _ = YYAlamofire.postForCache(url: url, parameters: parameters, cache: cache, success: success, failure: failure)
}

final class YYAlamofire {
    
    static func get(url: URLConvertible, parameters: [String: String]? = nil, success: @escaping (Any?) -> Void, failure: @escaping (String) -> String?) -> Alamofire.DataRequest {
        var parameters = parameters
        parameters = sign(params: parameters ?? [:])
        
        let key = getUrlString(url: url, params: parameters!)
        return Alamofire.request(url, method: .get, parameters: parameters, headers: ["Authorization": YYAppConfig.getOne(key: appConfig_user_token) ?? ""]).validate(contentType: ["application/json"]).responseJSON { (response) in
            yy_LogInfo(key)
            
            if let statusCode = response.response?.statusCode {
                if statusCode == 599 {
                    SVProgressHUD.showError(with: "请勿频繁获取数据")
                    return
                }
            }
            
            switch response.result {
            case .success:
                let (sucs, data) = analyzResponseData(value: response.result.value, url: key)
                if sucs {
                    success(data)
                } else {
                    if let errmsg = failure(data as? String ?? "没有错误信息") {
                        SVProgressHUD.showError(with: errmsg)
                    }
                }
            case .failure(let error):
                yy_reportError(error)
                if let errmsg = failure(error.localizedDescription) {
                    SVProgressHUD.showError(with: errmsg)
                }
            }
        }
    }
    
    static func post(url: URLConvertible, parameters: [String: String]? = nil, success: @escaping (Any?) -> Void, failure: @escaping (String) -> String?) -> Alamofire.DataRequest {
        var parameters = parameters
        parameters = sign(params: parameters ?? [:])
        
        let key = getUrlString(url: url, params: parameters!)
        return Alamofire.request(url, method: .post, parameters: parameters, headers: ["Authorization": YYAppConfig.getOne(key: appConfig_user_token) ?? ""]).validate(contentType: ["application/json"]).responseJSON { (response) in
            yy_LogInfo(key)
            
            if let statusCode = response.response?.statusCode {
                if statusCode == 599 {
                    SVProgressHUD.showError(with: "请勿频繁获取数据")
                    return
                }
            }
            
            switch response.result {
            case .success:
                let (sucs, data) = analyzResponseData(value: response.result.value, url: key)
                if sucs {
                    success(data)
                } else {
                    if let errmsg = failure(data as? String ?? "没有错误信息") {
                        SVProgressHUD.showError(with: errmsg)
                    }
                }
            case .failure(let error):
                yy_reportError(error)
                if let errmsg = failure(error.localizedDescription) {
                    SVProgressHUD.showError(with: errmsg)
                }
            }
        }
    }
    
    static func getForCache(url: URLConvertible, parameters: [String: String]? = nil, cache: (Any?) -> Bool, success: @escaping (Bool, Any?) -> Void, failure: @escaping (String, Any?) -> String?) -> Alamofire.DataRequest {
        var parameters = parameters
        parameters = sign(params: parameters ?? [:])
        
        let key = getUrlString(url: url, params: parameters!)
        let cacheValue = YYCache.getOne(key: key)
        if let cacheValue = cacheValue {
            let r = cache(cacheValue)
            if r {
                success(false, cacheValue)
            }
        }
        
        return Alamofire.request(url, method: .get, parameters: parameters, headers: ["Authorization": YYAppConfig.getOne(key: appConfig_user_token) ?? ""]).validate(contentType: ["application/json"]).responseJSON { (response) in
            yy_LogInfo(key)
            
            if let statusCode = response.response?.statusCode {
                if statusCode == 599 {
                    SVProgressHUD.showError(with: "请勿频繁获取数据")
                    return
                }
            }
            
            switch response.result {
            case .success:
                let (sucs, data) = analyzResponseData(value: response.result.value, url: key)
                if sucs {
                    YYCache.set(key: key, value: data!)
                    success(true, data)
                } else {
                    if let errmsg = failure(data as? String ?? "没有错误信息", cacheValue) {
                        SVProgressHUD.showError(with: errmsg)
                    }
                }
            case .failure(let error):
                yy_reportError(error)
                if let errmsg = failure(error.localizedDescription, cacheValue) {
                    SVProgressHUD.showError(with: errmsg)
                }
            }
        }
    }
    
    static func postForCache(url: URLConvertible, parameters: [String: String]? = nil, cache: (Any?) -> Bool, success: @escaping (Bool, Any?) -> Void, failure: @escaping (String, Any?) -> String?) -> Alamofire.DataRequest {
        var parameters = parameters
        parameters = sign(params: parameters ?? [:])
        
        let key = getUrlString(url: url, params: parameters!)
        let cacheValue = YYCache.getOne(key: key)
        if let cacheValue = cacheValue {
            let r = cache(cacheValue)
            if r {
                success(false, cacheValue)
            }
        }
        
        return Alamofire.request(url, method: .post, parameters: parameters, headers: ["Authorization": YYAppConfig.getOne(key: appConfig_user_token) ?? ""]).validate(contentType: ["application/json"]).responseJSON { (response) in
            yy_LogInfo(key)
            
            if let statusCode = response.response?.statusCode {
                if statusCode == 599 {
                    SVProgressHUD.showError(with: "请勿频繁获取数据")
                    return
                }
            }
            
            switch response.result {
            case .success:
                let (sucs, data) = analyzResponseData(value: response.result.value, url: key)
                if sucs {
                    YYCache.set(key: key, value: data!)
                    success(true, data)
                } else {
                    if let errmsg = failure(data as? String ?? "没有错误信息", cacheValue) {
                        SVProgressHUD.showError(with: errmsg)
                    }
                }
            case .failure(let error):
                yy_reportError(error)
                if let errmsg = failure(error.localizedDescription, cacheValue) {
                    SVProgressHUD.showError(with: errmsg)
                }
            }
        }
    }
    
    private static func getUrlString(url: URLConvertible, params: [String: String]) -> String {
        guard !params.isEmpty else {
            if let url = try? url.asURL() {
                return url.absoluteString
            } else {
                return ""
            }
        }
        
        var querys = [String]()
        for (key, value) in params {
            querys.append("\(key)=\(value)")
        }
        let urlParamsString = querys.joined(separator: "&")
        
        if let url = try? url.asURL() {
            return url.absoluteString.appending(url.query == nil ? "?\(urlParamsString)" : "&\(urlParamsString)")
        } else {
            return ""
        }
    }
    
    static func getUrlParams(url: URLConvertible) -> [String: String]! {
        if let url = try? url.asURL() {
            var params: [String: String] = [:]
            if let query = url.query {
                let querys = query.components(separatedBy: "&")
                
                for param in querys {
                    let items = param.components(separatedBy: "=")
                    params[items[0]] = items[1]
                }
            }
            return params
        }
        return nil
    }
    
}

